#ifndef __PLANTS_MANAGER_H__
#define __PLANTS_MANAGER_H__

#include <cstdint>
#include <functional>
#include <vector>
#include "SimpleSingleton.hpp"
#include "Engine/Random.hpp"
#include "Terrain/TerrainBrush.h"
#include "GameEnum.h"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    class Client;

    class PlantsManager : public SimpleSingletonItem
    {
        friend class SimpleSingleton;
    private:
        std::vector<std::vector<TerrainBrush>> m_treeBrushesByType;
        std::vector<int32_t> m_treeTrunksByType;
        std::vector<int32_t> m_treeLeavesByType;

    private:
        PlantsManager();
        ~PlantsManager();
        PlantsManager(const PlantsManager &) = delete;
        PlantsManager(PlantsManager &&) = delete;
        PlantsManager &operator=(const PlantsManager &) = delete;
        PlantsManager &operator=(PlantsManager &&) = delete;

        void createTreeBrush(TerrainBrush &terrainBrush, Random &random, int32_t woodIndex, int32_t leavesIndex, int32_t height, int32_t branchesCount, std::function<float(int32_t)> leavesProbabilityByHeight, std::function<float(int32_t)> branchesLengthByHeight);
        void createMimosaBrush(TerrainBrush &terrainBrush, Random &random, float size);

        float rangeProbability(float v, float a, float b, float c, float d);



    public:
        inline int32_t getTreeTrunkValue(TreeType treeType);
        inline int32_t getTreeLeavesValue(TreeType treeType);
        inline std::vector<TerrainBrush> &getTreeBrushes(TreeType treeType);

        float calculateTreeDensity(TreeType treeType, int32_t temperature, int32_t humidity, int32_t y);
        float calculateTreeProbability(TreeType treeType, int32_t temperature, int32_t humidity, int32_t y);
        int32_t generateRandomPlantValue(Random &random, int32_t groundValue, int32_t temperature, int32_t humidity, int32_t y);
        TreeType generateRandomTreeType(Random &random, int32_t temperature, int32_t humidity, int32_t y, float densityMultiplier = 1.0f);

        void loadGame();
    };

    inline int32_t PlantsManager::getTreeTrunkValue(TreeType treeType)
    {
        return m_treeTrunksByType[(int32_t)treeType];
    }
    inline int32_t PlantsManager::getTreeLeavesValue(TreeType treeType)
    {
        return m_treeLeavesByType[(int32_t)treeType];
    }
    inline std::vector<TerrainBrush> &PlantsManager::getTreeBrushes(TreeType treeType)
    {
        return m_treeBrushesByType[(int32_t)treeType];
    }

} // namespace PocketSurvival


#endif
